package com.magicalcoder.pigeon.server;

import com.alibaba.fastjson.JSON;
import com.magicalcoder.pigeon.common.constant.Status;
import com.magicalcoder.pigeon.common.message.PigeonRequest;
import com.magicalcoder.pigeon.common.message.PigeonResponse;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * Created by hzhedongyu on 2017/5/24.
 */
public class ServerHandler extends SimpleChannelInboundHandler<PigeonRequest>{

    private Logger logger = LoggerFactory.getLogger(ServerHandler.class);

    private Map<String,Object> serviceImplBeanMap;//储存了接口名称和实现类实例映射 客户端只有接口 服务端有实现类 这么就对应起来了

    public ServerHandler(Map<String, Object> serviceImplBeanMap) {
        this.serviceImplBeanMap = serviceImplBeanMap;
    }

    //处理客户端请求
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, PigeonRequest request) throws Exception {
        logger.debug("客户端IP可以做白名单:"+channelHandlerContext.channel().remoteAddress().toString());
        //线程池控制 避免崩了
        ServerWorkerPool.get().accept(new Runnable() {
            @Override
            public void run() {
                PigeonResponse response = invokeImpl(request);
                channelHandlerContext.writeAndFlush(response).addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture channelFuture) throws Exception {
                        logger.debug("服务端返回:"+ JSON.toJSONString(response));
                    }
                });
            }
        });
    }

    //反射 执行 这里做日志 统计等等都可以
    private PigeonResponse invokeImpl(PigeonRequest request){
        PigeonResponse response = new PigeonResponse();
        try {
            response.setCode(Status.OK);
            response.setRequestId(request.getRequestId());
            response.setMessage("成功");

            String interfaceName = request.getInterfaceName();//接口名称
            Object serviceImplBean = serviceImplBeanMap.get(interfaceName);// 请帮我找实现类实例

            //java反射
//            Method method = serviceImplBean.getClass().getMethod(request.getMethodName(),request.getParamTypes());
//            method.setAccessible(true);//提升反射速度
//            Object invokeValue = method.invoke(serviceImplBean,request.getParams());

            // Cglib reflect
            FastClass serviceFastClass = FastClass.create(serviceImplBean.getClass());
            FastMethod serviceFastMethod = serviceFastClass.getMethod(request.getMethodName(), request.getParamTypes());
            Object invokeValue = serviceFastMethod.invoke(serviceImplBean, request.getParams());
            //TODO 这里可用限制大小 如果超过1M则报错 等等用来限流
            response.setInfo(invokeValue);
        }catch (Exception e){
            response.setCode(Status.EXCEPTION);
            e.printStackTrace();
            response.setInfo(e);
        }
        return response;
        //也可以考虑cglib 性能更优 后期再说吧
    }
}
